package org.example.Controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashSet;
import java.util.List;

import static java.util.stream.Collectors.toList;

@RestController()
public class PublicController {

    @Autowired
    @Qualifier("redisTemplate1")
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * 执行
     *
     * @param key
     * @return
     */
    @RequestMapping("/execTest")
    public List<Object> execTest(String key) {
        //设置启用事务支持
        redisTemplate.setEnableTransactionSupport(true);
        //标记事务块的开始。命令将被排队，然后可以通过调用exec（）执行或使用discard（）回滚
        redisTemplate.multi();
        redisTemplate.opsForValue().set("{123}username", "xds");
        redisTemplate.opsForValue().set("{123}4521", "abc");
        return redisTemplate.exec();
    }


    /**
     * 通过 key 获取 value
     * <p>
     * pattern：message:xxx:yyy:id:
     * limit：每次限制筛选的数量，不建议 Integer.MAX_VALUE
     */
    public List<Object> assembleScanValues(String pattern, Long limit) {
        HashSet<String> values = assembleScanKeys(pattern, limit);
        return redisTemplate.opsForValue().multiGet(values).stream().collect(toList());
    }

    /**
     * 组装 scan 的结果集
     */
    public HashSet<String> assembleScanKeys(String pattern, Long limit) {
        HashSet<String> set = new HashSet<>();
        Cursor<String> cursor = scan(redisTemplate, pattern+"*", limit);
        while (cursor.hasNext()) {
            set.add(cursor.next());
        }
        try {
            cursor.close();
        } catch (Exception e) {
            System.out.println("关闭 redis connection 失败");
        }
        return set;
    }

    /**
     * 自定义 redis scan 操作
     */
    private Cursor<String> scan(RedisTemplate redisTemplate, String pattern, Long limit) {
        ScanOptions options = ScanOptions.scanOptions().match(pattern).count(limit).build();
        RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
        return (Cursor) redisTemplate.executeWithStickyConnection(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection redisConnection)
                    throws org.springframework.dao.DataAccessException {
                return new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize);
            }
        });
    }

    @RequestMapping("/executeWithStickyConnection1")
    public List<Object> executeWithStickyConnection1(String pattern, long pageSize) {
        List<Object> objects = assembleScanValues(pattern, pageSize);//关闭cursor
        return objects;
    }

}
